package src.week7.SHIYAN4.JavaSocket;

/**
 * @Author： 20192315裴湘瑞
 * @Date: 2020/10/27 19:21
 * @Version: 1.0
 * @Target：编写服务器端程序
 * @Requirement：
 */
import java.awt.BorderLayout;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;

//服务器窗口创建
/*一个框框，两个按钮*/
public class ServerChat extends JFrame{
    //设置服务器窗口——一个框框
    JTextArea serverTa = new JTextArea();
    //创建服务器窗口——两个按钮
    private JPanel btnTool = new JPanel();
    private JButton starBtn = new JButton("start");
    private JButton stopBtn = new JButton("stop");

    //设置服务器端socket的端口号
    private static final int PORT = 8888;
    //创建服务器端socket
    private ServerSocket ss = null;
    private Socket s = null;
    //设置服务器启动的标志
    private boolean isStart = false;
    //设置连接到服务器上的客户socket数组
    private ArrayList<ClientConn> cclist=new ArrayList<ClientConn>();
    //初始化服务器窗口
    public void init() {
        //设置窗口标题
        this.setTitle("ServerView");
        //设置窗口样式
        this.add(serverTa,BorderLayout.CENTER);
        btnTool.add(starBtn);
        btnTool.add(stopBtn);
        this.add(btnTool,BorderLayout.SOUTH);
        //设置窗口总大小
        this.setBounds(0, 0, 500, 500);
        //设置serverTa不可输入
        serverTa.setEditable(false);
        //点击叉号关闭窗口，同时停止服务器运行，后面改进
        //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //判断服务器是否启动
        if(isStart) {
            serverTa.append("Server started.\\n");
        }else {
            serverTa.append("Server not start."+"\n");
        }
        //监听开始按钮，启动服务器
        starBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    if(ss==null) {
                        ss=new ServerSocket(PORT);
                    }
                    isStart = true;
                    serverTa.append("Server started."+"\n");
                }catch(IOException e1) {
                    e1.printStackTrace();
                }


            }

        });
        //监听停止按钮，关闭服务器
        stopBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //关机
                isStart = false;
                try {
                    if(s!=null) {
                        s.close();
                    }
                    if(ss!=null) {
                        ss.close();
                    }
                    serverTa.append("Server stopped");
                    System.exit(0);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });
        //监听窗口（叉号）
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                //关机
                isStart = false;
                try {
                    if(s!=null) {
                        s.close();
                    }
                    if(ss!=null) {
                        ss.close();
                    }
                    serverTa.append("Server stopped");
                    System.exit(0);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });
        this.setVisible(true);

        startServer();


    }

    /*服务器启动方法*/
    public void startServer() {
        //正式创建服务器socket
        try {
            try {
                ss = new ServerSocket(PORT);
                isStart = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //只要服务器运行就一直等待客户连接,接受多个客户端连接
            while (isStart) {
                //获取客户端socket对象
                s = ss.accept();
                //将该对象添加进数组
                cclist.add(new ClientConn(s));
                //在控制台显示相关信息
                System.out.println("A Client connected" + s.getInetAddress() + "/" + s.getPort()+"\n");
                //在服务器窗口显示相关信息
                serverTa.append("A Client connected" + s.getInetAddress() + "/" + s.getPort()+"\n");
            }
        }catch (SocketException e3) {
            System.out.println("Sever stopped");
            serverTa.append("Server stopped");
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*服务器停止方法*/
    public void stopServer() {

    }

    /* 服务器接收数据方法,应该是多线程的接收*/
//	public void reciveStr() {
//		try {
//			dis = new DataInputStream(s.getInputStream());
//			String str = dis.readUTF();
//			System.out.println(str);
//			serverTa.append(str);
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//
//	}

    /*该对象是所有连接到服务器端的连接对象*/
    class ClientConn implements Runnable{
        Socket s= null;
        public ClientConn(Socket s) {
            this.s= s;
            //得到一个s就创建一个线程，并运行下面的try/catch
            (new Thread(this)).start();
        }

        //同时接受客户端信息-多线程的接收
        public void run() {
            try {
                //使用getinputstream获取网络输入流（客户端输入流）
                DataInputStream dis = new DataInputStream(s.getInputStream());
                while (isStart) {
                    //读取输入流中信息
                    String str = dis.readUTF();
                    //在控制台和服务器窗口打印
                    System.out.println(s.getInetAddress()+"|"+s.getPort()+"说："+str + "\n");
                    serverTa.append(s.getInetAddress()+"|"+s.getPort()+"说："+str + "\n");
                    String strsend = s.getInetAddress()+"|"+s.getPort()+"说："+str + "\n";
                    //遍历后再发送
                    Iterator<ClientConn> it=cclist.iterator();
                    while(it.hasNext()) {
                        ClientConn o=it.next();
                        o.resend(strsend);
                    }
                }
            }catch(SocketException e) {
                System.out.println("A Client leave");
                serverTa.append("a Client leave："+s.getInetAddress()+"|"+s.getPort()+"\n");
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }
        }
        //服务器分发数据，通过遍历，发生给每个客户端,在客户端同样要多线程的接收
        public void resend(String str) {
            try {
                DataOutputStream dos = new DataOutputStream(this.s.getOutputStream());
                dos.writeUTF(str);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }
    public static void main(String[] args) {
        ServerChat sc = new ServerChat();
        sc.init();
    }

}
